/**
 * @File:    example_flexible_button.c
 * @Author:  MurphyZhao
 * @Date:    2018-09-29
 *
 * Copyright (c) 2018-2018 MurphyZhao <d2014zjt@163.com>
 *               https://github.com/zhaojuntao
 * All rights reserved.
 * License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Change logs:
 * Date        Author       Notes
 * 2018-09-29  MurphyZhao   First add
 *
 */

#include <rtthread.h>
#include "flexible_button.h"
#include <stdint.h>
#include "ACM32Fxx_HAL.h"
#include "lcd_XJR80260H.h"
#define ENUM_TO_STR(e) (#e)
struct rt_mailbox key_mb;
static char keymb_pool[64];
extern GPIO_InitTypeDef GPIOA_Handle;
extern rt_sem_t lcd_sem;
extern int s_index;
extern int s_index1;
static char *enum_event_string[] = {
    ENUM_TO_STR(FLEX_BTN_PRESS_DOWN),
    ENUM_TO_STR(FLEX_BTN_PRESS_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_DOUBLE_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_REPEAT_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_START),
    ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_START),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_MAX),
    ENUM_TO_STR(FLEX_BTN_PRESS_NONE),
};

static char *enum_btn_id_string[] = {
    ENUM_TO_STR(USER_BUTTON_0),
    ENUM_TO_STR(USER_BUTTON_1),
    ENUM_TO_STR(USER_BUTTON_2),
    ENUM_TO_STR(USER_BUTTON_3),
    ENUM_TO_STR(USER_BUTTON_MAX),
};
typedef enum
{
    USER_BUTTON_0 = 0,
    USER_BUTTON_1,
    USER_BUTTON_2,
    USER_BUTTON_3,
    USER_BUTTON_MAX
} user_button_t;
static flex_button_t user_button[USER_BUTTON_MAX];

static void user_btn_event(void *arg)
{
    flex_button_t *btn = (flex_button_t *)arg;
    //    rt_kprintf("id: [%d - %s]  event: [%d - %30s]  repeat: %d\n",
    //        btn->id, enum_btn_id_string[btn->id],
    //        btn->event, enum_event_string[btn->event],
    //        btn->click_cnt);
    switch (btn->id)
    {
    case USER_BUTTON_0:
    {
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_DOWN:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            lcd_reset_s(s_index);
            s_index++;
            if (s_index == 19)
                s_index = 1;
            lcd_set_s(s_index);
            break;
        case FLEX_BTN_PRESS_DOUBLE_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        default:
            break;
        }
        break;
    }

    case USER_BUTTON_1:
    {
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_DOWN:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        case FLEX_BTN_PRESS_CLICK:

            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            lcd_reset_s(s_index);
            s_index++;
            if (s_index == 19)
                s_index = 1;
            lcd_set_s(s_index);
            break;
        case FLEX_BTN_PRESS_DOUBLE_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        default:
            break;
        }
        break;
    }
    case USER_BUTTON_2:
    {
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_DOWN:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            lcd_reset_s(s_index);
            s_index++;
            if (s_index == 19)
                s_index = 1;
            lcd_set_s(s_index);
            break;
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        case FLEX_BTN_PRESS_DOUBLE_CLICK:

            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        default:
            break;
        }
        break;
    }
    case USER_BUTTON_3:
    {
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_DOWN:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        case FLEX_BTN_PRESS_DOUBLE_CLICK:
            rt_kprintf("%s : %s\n", enum_btn_id_string[btn->id], enum_event_string[btn->event]);
            break;
        default:
            break;
        }
        break;
    }
    default:
        break;
    }
}
static uint8_t common_btn_read(void *arg)
{
    uint8_t value = 0;

    flex_button_t *btn = (flex_button_t *)arg;

    switch (btn->id)
    {
    case USER_BUTTON_0:
        value = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);
        break;
    case USER_BUTTON_1:
        value = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4);
        break;
    case USER_BUTTON_2:
        value = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);
        break;
    case USER_BUTTON_3:
        value = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
        break;
    default:
        RT_ASSERT(0);
    }

    return value;
}
static void button_scan(void *arg)
{
    while (1)
    {
        flex_button_scan();
        rt_thread_mdelay(20);
    }
}
void key_gpio_init(void)
{
    GPIOA_Handle.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
    GPIOA_Handle.Mode = GPIO_MODE_INPUT;
    GPIOA_Handle.Pull = GPIO_PULLUP;
    GPIOA_Handle.Alternate = GPIO_FUNCTION_0;

    HAL_GPIO_Init(GPIOA, &GPIOA_Handle);
}
static void user_button_init(void)
{
    int i;
    rt_memset(&user_button[0], 0x0, sizeof(user_button));
    for (i = 0; i < USER_BUTTON_MAX; i++)
    {
        user_button[i].id = i;
        user_button[i].usr_button_read = common_btn_read;
        user_button[i].cb = user_btn_event;
        user_button[i].pressed_logic_level = 0;
        user_button[i].short_press_start_tick = 100;
        user_button[i].long_press_start_tick = 200;
        user_button[i].long_hold_start_tick = 300;

        flex_button_register(&user_button[i]);
    }
}
static struct rt_thread flex_btn_tid;
static rt_uint8_t flex_btn_thread_stack[256];
#define BTN_THREAD_PRIORITY 5
#define BTN_THREAD_TICK 20
int flex_button_main(void)
{
    key_gpio_init();
    user_button_init();

    rt_mb_init(&key_mb,
               "mbt",
               &keymb_pool[0],
               sizeof(keymb_pool) / 4,
               RT_IPC_FLAG_FIFO);
    rt_thread_init(&flex_btn_tid, "flex_btn", button_scan,
                   RT_NULL, &flex_btn_thread_stack[0], sizeof(flex_btn_thread_stack),
                   BTN_THREAD_PRIORITY, BTN_THREAD_TICK);

    rt_thread_startup(&flex_btn_tid);
    return 0;
}
INIT_APP_EXPORT(flex_button_main);
